//
//  CameraViewController.swift
//  ZhiTing
//
//  Created by macbook on 2022/4/12.
//

import Alamofire
import UIKit
import Kingfisher
import Combine

#if !(targetEnvironment(simulator))
class CameraViewController: BaseViewController {
    var device: Device?
    var myUID = ""
    var mypwd = ""
    var deviceID: Int? {
        didSet {
            guard let id = deviceID else {return}
            //通过id，获取设备
            ApiServiceManager.shared.deviceDetail(area: AuthManager.shared.currentArea, device_id: id) { [weak self] (response) in
                guard let self = self else { return }
                self.device = response.device_info
                self.device?.plugin_id = response.device_info.plugin?.id ?? ""
                let camera = CameraModel.deserialize(from: self.device?.sync_data)
                self.myUID = camera?.uid ?? ""
                self.mypwd = camera?.pwd ?? ""
                self.headerView.nameLabel.text = self.device?.name
                self.title = self.device?.name ?? "IPC摄像头IC1".localizedString
                self.connectVideo()
            } failureCallback: { [weak self] (statusCode, errMessage) in
                guard let self = self else { return }
                self.showToast(string: errMessage)
            }
        }
    }
    var displayView: IJKSDLGLView?
    var videoData:NSData!
    var cameraFunciondatas = [CameraFuctionModel]()
    var cameraWidth = UIScreen.main.bounds.width
    var cameraHeight = UIScreen.main.bounds.width * 2/3
    //是否需要截屏
    var isNeedSnapshot = false
    //是否收藏位置
    var isCollectingPlace = false
    //是否正在录制
    var isRecord = false
    //是否展开功能栏
    var isShowFunctionView = false
    //是否正在开启监听
    var isOpenVoice = false
    //是否正在开启对讲
    var isOpenTalk = false
    //是否正在开启上下巡航
    var isOpenUpdown = false
    //是否正在开启左右巡航
    var isOpenLeftRight = false
    //是否正在锁定屏幕
    var isLockScreen = false
    //第几个预设位置
    var currentCommonPlace = 0
    //当前控件是否隐藏
    var isShowControlView = true
    //隐藏控件通知
    let publisher = PassthroughSubject<(), Never>()
    //开启计时器
    var timer: Timer?
    //录制时间
    var secondCount = 0
    //当前清晰度
    var currentClarity = Clarity().smooth
    //当前是否为展示清晰度
    var isShowClarityView = false
    //是否为竖屏
    var isPortrait = true
    var startCenter = CGPoint.zero
    var direction = CircleConsoleMoveDirection.CircleConsoleMoveDirectionNone
    //是否正在操作中
    var isControlling = false
    var isCurrentVC = true
    
    
    private lazy var settingButton = Button().then {
        $0.setImage(.assets(.settings), for: .normal)
        $0.frame.size = CGSize(width: 18, height: 18)
        $0.clickCallBack = { [weak self] _ in
            guard let self = self else { return }
            let vc = DeviceDetailViewController()
            vc.device_id = self.device?.id ?? -1
            vc.area = AuthManager.shared.currentArea
            self.navigationController?.pushViewController(vc, animated: true)
        }
    }
    
    private lazy var centerview = UIView().then {
        $0.backgroundColor = .custom(.white_ffffff)
    }
    
    //遥控杆
    private lazy var circleConsoleView = CircleConsoleView().then {
        $0.backgroundColor = .clear
    }
    
    //控制栏
    private lazy var controllerView = CameraControlView().then {
        $0.backgroundColor = .custom(.white_ffffff)
        $0.isHidden = true
    }

    //视频底部视图
    private lazy var downView = CameraDownControlView().then {
        $0.backgroundColor = .clear
    }
    
    //横屏操作栏
    private lazy var landscapeFunctionView = LandscapeFunctionView().then {
        $0.backgroundColor = .clear
        $0.collectionView.isScrollEnabled = false
        $0.isHidden = true
    }
    
    //横屏锁屏按钮
    lazy var lockBtn = Button().then {
        $0.setImage(.assets(.camera_lock_landscape), for: .normal)
        $0.setImage(.assets(.camera_lock_landscape_selected), for: .selected)
        $0.isEnhanceClick = true
        $0.isHidden = true
        $0.clickCallBack = { [weak self] _ in
            self?.lockTheFrames()
        }
    }

    
    //功能列表
    private lazy var flowLayout = UICollectionViewFlowLayout().then {
        $0.itemSize = CGSize(width: ZTScaleValue(25), height:  ZTScaleValue(25))
        //行列间距
        $0.minimumLineSpacing = 10
        let space = (Screen.screenWidth - ZTScaleValue(220)) / 4.0
        $0.minimumInteritemSpacing = space
    }
    
    lazy var functionCollectionView = UICollectionView(frame: .zero, collectionViewLayout: flowLayout).then{
        $0.backgroundColor = .clear
        $0.backgroundColor = .clear
        $0.delegate = self
        $0.dataSource = self
        $0.showsHorizontalScrollIndicator = false
        $0.showsVerticalScrollIndicator = false
        $0.alwaysBounceVertical = true
        $0.alwaysBounceHorizontal = false
        $0.register(CameraFunctionCell.self, forCellWithReuseIdentifier: CameraFunctionCell.reusableIdentifier)
    }
    
    
    private lazy var placehoderView = UIView().then {
        $0.backgroundColor = .black
    }

    private lazy var placehoderImg = ImageView().then {
        $0.image = .assets(.camera_placehoder_icon)
    }
    
    private lazy var placehoderLabel = Label().then {
        $0.text = "摄像头连接中..."
        $0.textColor = .custom(.gray_94a5be)
        $0.font = .font(size: 14, type: .bold)
        $0.textAlignment = .center
    }
    
    private lazy var headerView = CameraHeaderView().then {
        $0.nameLabel.text = device?.name ?? "IPC摄像头IC1"
        $0.backgroundColor = .clear
        $0.isHidden = true
        $0.isUserInteractionEnabled = true
    }
    
    private lazy var recordBGView = UIView().then{
        $0.backgroundColor = .black.withAlphaComponent(0.5)
        $0.isHidden = true
    }
    
    private lazy var timeLabel = Label().then {
        $0.text = "00:00"
        $0.backgroundColor = .clear
        $0.textColor = .custom(.white_ffffff)
        $0.font = .font(size: 10, type: .bold)
        $0.textAlignment = .left
    }

    private lazy var redDot = UIView().then {
        $0.backgroundColor = .red
        $0.layer.cornerRadius = 3
        $0.clipsToBounds = true
    }
    
    private lazy var clarityView = ChangeClarityView().then {
        $0.backgroundColor = .clear
        $0.isHidden = true
    }
    
    override init() {
        super.init()
        VSNet.shareinstance()?.pppp_Initialize()
        VSNet.shareinstance()?.xqp2P_NetworkDetect()
        VSNet.shareinstance()?.xqp2P_Initialize()
    }
    // MARK: - Life Cycle && Update UI
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupFunctionDatas()
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        self.title = device?.name ?? "IPC摄像头IC1".localizedString
        self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: self.settingButton)
        if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
            appDelegate.isAllOrientation = true
        }
        isCurrentVC = true
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        isCurrentVC = false
    }
    
    deinit {
        //退出视频预览
        if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
            appDelegate.isAllOrientation = false
        }

        VSNet.shareinstance().stopLivestream(self.myUID)
        VSNet.shareinstance().stopAll()
        VSNet.shareinstance().stop(myUID)

        DispatchQueue.global().async {
            VSNet.shareinstance()?.pppp_DeInitialize()
            VSNet.shareinstance()?.xqp2P_DeInitialize()
        }
    }
    
    //屏幕发生旋转
    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        if !isCurrentVC {return}
        if size.width > size.height {//横屏
            ZTLog("当前为横屏")
            setupLandscapeUI(size: size)
        }else{//竖屏
            ZTLog("当前为竖屏")
            setupPortraitUI(size: size)
        }
    }
    
    override func setupViews() {
        view.addSubview(placehoderView)
        placehoderView.addSubview(placehoderImg)
        placehoderView.addSubview(placehoderLabel)
        //功能列表
        view.addSubview(functionCollectionView)
        view.addSubview(landscapeFunctionView)
        view.addSubview(centerview)
        //遥控杆
        view.addSubview(circleConsoleView)
        //控制栏
        view.addSubview(controllerView)
        //视频底部视图
        view.addSubview(downView)
        //底部控制栏
        downView.updateUI(isPortrait: isPortrait)
        
        view.addSubview(headerView)
        view.addSubview(recordBGView)
        recordBGView.addSubview(redDot)
        recordBGView.addSubview(timeLabel)
        view.addSubview(clarityView)
        view.addSubview(lockBtn)
        
        controllerView.clickCallback = { [weak self] index in
            guard let self = self else {return}
            
            switch index {
            case 0://左右巡航
                self.leftRightAction()
            case 1://上下巡航
                self.updownAction()
            case 2://回放
                let vc = RemoteSegmentViewController()
                vc.device = self.device ?? Device()
                vc.myUID = self.myUID
                vc.mypwd = self.mypwd
                self.navigationController?.pushViewController(vc, animated: true)
            case 3://锁定画面
                self.lockTheFrames()
            case 4://常看位置
                self.showCommonPlaceAlert()
            case 5://收藏位置
                self.collectionPlace()
            default:
                break
            }
        }
                
        circleConsoleView.moveCallback = {[weak self] direction in
            guard let self = self else {return}
            if self.cameraFunciondatas[4].isSelected {
                //隐藏操作栏
                self.cameraFunciondatas[4].isSelected = false
                self.controllerView.isHidden = !self.cameraFunciondatas[4].isSelected
                self.functionCollectionView.reloadData()
            }
            if self.isLockScreen {return}

            //正在操作中
            self.isControlling = true
            switch direction {
            case .CircleConsoleMoveDirectionUp:
                self.moveFrom(directionNum: 0, status: 1)
            case .CircleConsoleMoveDirectionLeft:
                ZTLog("向左移动")
                self.moveFrom(directionNum: 2, status: 1)

            case .CircleConsoleMoveDirectionDown:
                ZTLog("向下移动")
                self.moveFrom(directionNum: 1, status: 1)
            case .CircleConsoleMoveDirectionRight:
                ZTLog("向右移动")
                self.moveFrom(directionNum: 3, status: 1)
            default:
                break
            }
        }
        
        
        circleConsoleView.stopCallback = {[weak self] direction in
            guard let self = self else {return}
            if self.isLockScreen {return}
            //停止操作中
            self.isControlling = false
            self.publisher.send(())
            
            switch direction {
            case .CircleConsoleMoveDirectionUp:
                ZTLog("停止向上移动")
                self.moveFrom(directionNum: 0, status: 0)
            case .CircleConsoleMoveDirectionLeft:
                ZTLog("停止向左移动")
                self.moveFrom(directionNum: 2, status: 0)
            case .CircleConsoleMoveDirectionDown:
                ZTLog("停止向下移动")
                self.moveFrom(directionNum: 1, status: 0)
            case .CircleConsoleMoveDirectionRight:
                ZTLog("停止向右移动")
                self.moveFrom(directionNum: 3, status: 0)
            default:
                break
            }
        }
        
        downView.clickCallback = {[weak self] index in
            guard let self = self else {return}
            switch index {
            case 0:
                ZTLog("点击全屏")
                self.intoFullScreen()
            case 1:
                ZTLog("左右巡航")
                self.leftRightAction()
            case 2:
                ZTLog("上下巡航")
                self.updownAction()
            case 3:
                ZTLog("点击切换流畅度")
                self.showClarityView()
            default:
                break
            }
        }
        
        landscapeFunctionView.clickCallback = {[weak self] index in
            guard let self = self else {return}
            switch index {
            case 0://截图
                self.screenshotAction()
            case 1://录制
                self.recordVideoAction()
            case 2://对讲
                self.talkAction()
            case 3://监听
                self.audioAction()
            default:
                break
            }
        }
        
        headerView.gobackCallback = {[weak self] in
            guard let self = self else {return}
            ZTLog("点击全屏")
                self.intoFullScreen()
        }
        
        clarityView.clickCallback = {[weak self] index in
            guard let self = self else {return}
            self.currentClarity = index
            self.changeClarity(value: index)
            self.hideClarityView()
        }
        
        clarityView.tapCallback = {[weak self] in
            guard let self = self else {return}
            self.hideClarityView()
        }
    }
    
    override func setupConstraints() {
        
        placehoderView.snp.makeConstraints {
            $0.top.equalTo(Screen.k_nav_height)
            $0.left.right.equalToSuperview()
            $0.height.equalTo(self.view.bounds.width * 2/3)
        }
        
        placehoderImg.snp.makeConstraints {
            $0.center.equalToSuperview()
            $0.width.equalTo(33.5)
            $0.height.equalTo(41.5)
        }
        
        placehoderLabel.snp.makeConstraints {
            $0.top.equalTo(placehoderImg.snp.bottom).offset(13.5)
            $0.centerX.equalToSuperview()
            $0.width.greaterThanOrEqualTo(100)
        }
        
        functionCollectionView.snp.makeConstraints {
            $0.top.equalTo(placehoderView.snp.bottom).offset(ZTScaleValue(20))
            $0.left.equalTo(ZTScaleValue(35))
            $0.right.equalTo(-ZTScaleValue(35))
            $0.height.equalTo(ZTScaleValue(30))
        }
        
        centerview.snp.makeConstraints {
            $0.top.equalTo(functionCollectionView.snp.bottom)
            $0.left.right.bottom.equalToSuperview()
        }
        
        circleConsoleView.snp.makeConstraints {
            $0.center.equalTo(centerview)
            $0.width.height.equalTo(200)
        }
        
        controllerView.snp.makeConstraints {
            $0.top.equalTo(functionCollectionView.snp.bottom).offset(15)
            $0.left.right.equalToSuperview()
            $0.height.equalTo(110)
        }

        downView.snp.makeConstraints {
            $0.bottom.equalTo(placehoderView.snp.bottom)
            $0.left.right.equalToSuperview()
            $0.height.equalTo(40)
        }
        
        headerView.snp.makeConstraints {
            $0.top.left.right.equalToSuperview()
            $0.height.equalTo(Screen.k_nav_height)
        }
        
        lockBtn.snp.makeConstraints {
            $0.top.equalTo(headerView.snp.bottom).offset(60)
            $0.width.height.equalTo(50)
            $0.left.equalTo(30)
        }
        
        landscapeFunctionView.snp.makeConstraints {
            $0.right.equalTo(-10)
            $0.top.equalTo(headerView.snp.bottom)
            $0.width.equalTo(100)
            $0.bottom.equalTo(downView.snp.top)
        }
        
        recordBGView.snp.makeConstraints {
            $0.top.equalTo(placehoderView).offset(10)
            $0.right.equalTo(placehoderView).offset(-15)
            $0.height.equalTo(20)
            $0.width.equalTo(50)
        }
        
        redDot.snp.makeConstraints {
            $0.centerY.equalToSuperview()
            $0.left.equalTo(6)
            $0.width.height.equalTo(6)
        }
        
        timeLabel.snp.makeConstraints {
            $0.centerY.equalToSuperview()
            $0.left.equalTo(redDot.snp.right).offset(6)
            $0.right.equalTo(-6)
        }
        
        clarityView.snp.makeConstraints {
            $0.edges.equalTo(placehoderView)
        }
    }
    
    override func setupSubscriptions() {
        publisher
            .debounce(for: .seconds(3), scheduler: DispatchQueue.main)
            .receive(on: DispatchQueue.main)
            .sink { [weak self] _ in
                guard let self = self else { return }
                if !self.isControlling {
                    self.hiddenControlView()
                }
            }
            .store(in: &cancellables)
    }
    
    private func setupFunctionDatas(){
        let cameraShot = CameraFuctionModel()
        cameraShot.normalIcon = .assets(.camera_shot)
        cameraShot.selectedIcon = .assets(.camera_shot)
        let cameraRecord = CameraFuctionModel()
        cameraRecord.normalIcon = .assets(.camera_record)
        cameraRecord.selectedIcon = .assets(.camera_record_selected)
        let cameraTalk = CameraFuctionModel()
        cameraTalk.normalIcon = .assets(.camera_talk)
        cameraTalk.selectedIcon = .assets(.camera_talk_selected)
        let cameraAudio = CameraFuctionModel()
        cameraAudio.normalIcon = .assets(.camera_audio)
        cameraAudio.selectedIcon = .assets(.camera_audio_selected)
        let cameraFunction = CameraFuctionModel()
        cameraFunction.normalIcon = .assets(.camera_function)
        cameraFunction.selectedIcon = .assets(.camera_function_selected)
        cameraFunciondatas = [cameraShot, cameraRecord, cameraTalk, cameraAudio, cameraFunction]
        //刷新数据
        functionCollectionView.reloadData()
    }

    
    private func setupGLView(){
        if displayView != nil {
            return
        }
        placehoderView.layoutIfNeeded()
        displayView = IJKSDLGLView(frame:placehoderView.frame)
        displayView?.backgroundColor = UIColor.black
        displayView?.isUserInteractionEnabled = true
        displayView?.addGestureRecognizer(UITapGestureRecognizer.init(target: self, action: #selector(tapAction)))
        displayView?.addGestureRecognizer(UIPanGestureRecognizer.init(target: self, action: #selector(handlePan(pan:))))
        self.view.addSubview(displayView!)
        self.view.bringSubviewToFront(circleConsoleView)
        self.view.bringSubviewToFront(controllerView)
        self.view.bringSubviewToFront(downView)
        if isPortrait {
            
        }else{
            self.view.bringSubviewToFront(headerView)
            self.view.bringSubviewToFront(landscapeFunctionView)
            self.view.bringSubviewToFront(lockBtn)
        }
        if !recordBGView.isHidden {
            view.bringSubviewToFront(recordBGView)
        }
    }
    
    private func intoFullScreen(){
        DispatchQueue.main.async {
            if UIDevice.current.orientation == .portrait {
                let oriention = UIInterfaceOrientation.landscapeRight // 设置屏幕为横屏
                UIDevice.current.setValue(oriention.rawValue, forKey: "orientation")
                UIViewController.attemptRotationToDeviceOrientation()
            }else{
                //强制归正：
                let oriention = UIInterfaceOrientation.portrait // 设置屏幕为竖屏
                UIDevice.current.setValue(oriention.rawValue, forKey: "orientation")
                UIViewController.attemptRotationToDeviceOrientation()
            }
        }
    }
    
    //横屏布局
    private func setupLandscapeUI(size: CGSize){
        navigationController?.navigationBar.isHidden = true
        isPortrait = false
        if isShowClarityView {
            hideClarityView()
        }
        displayView?.removeFromSuperview()
        displayView = nil
        cameraWidth = size.width
        cameraHeight = size.height

        placehoderView.snp.remakeConstraints {
            $0.edges.equalToSuperview()
        }
        //圆盘背景图更换
        circleConsoleView.bgImageView.image = .assets(.landscape_ConsoleBackgroundImage_normal)
        circleConsoleView.isPortrait = false
        circleConsoleView.snp.remakeConstraints {
            $0.bottom.equalTo(-30)
            $0.left.equalTo(50)
            $0.width.height.equalTo(160)
        }
        headerView.isHidden = false
        //底部控制栏
        downView.updateUI(isPortrait: isPortrait)
        landscapeFunctionView.isHidden = false
        lockBtn.isHidden = false
    }
    
    //竖屏布局
    private func setupPortraitUI(size: CGSize){
        navigationController?.navigationBar.isHidden = false
        isPortrait = true
        if isShowClarityView {
            hideClarityView()
        }
        displayView?.removeFromSuperview()
        displayView = nil
        cameraWidth = size.width
        cameraHeight = size.width * 2/3
        
        placehoderView.snp.remakeConstraints {
            $0.top.equalTo(Screen.k_nav_height)
            $0.left.right.equalToSuperview()
            $0.height.equalTo(cameraHeight)
        }
        //圆盘背景图更换
        circleConsoleView.bgImageView.image = .assets(.protrait_ConsoleBackgroundImage_normal)
        circleConsoleView.isPortrait = true
        circleConsoleView.snp.remakeConstraints {
            $0.center.equalTo(centerview)
            $0.width.height.equalTo(200)
        }
        //底部控制栏
        downView.updateUI(isPortrait: isPortrait)
        headerView.isHidden = true
        landscapeFunctionView.isHidden = true
        lockBtn.isHidden = true

    }
    
}

// MARK: - Function
extension CameraViewController {
    
    
    private func showClarityView(){
        isShowClarityView = true
        isShowControlView = false
        downView.isHidden = true
        clarityView.isHidden = false
        clarityView.selectedClarity = currentClarity
        clarityView.collectionView.reloadData()
        view.bringSubviewToFront(clarityView)
        if isPortrait {
            clarityView.snp.remakeConstraints {
                $0.edges.equalTo(placehoderView)
            }
        }else{
            landscapeFunctionView.isHidden = true
            circleConsoleView.isHidden = true
            clarityView.snp.remakeConstraints {
                $0.top.right.bottom.equalTo(placehoderView)
                $0.width.equalTo(160)
            }
        }
        clarityView.updateUI(isPortrait: isPortrait)
    }
    
    private func hideClarityView(){
        isShowClarityView = false
        downView.isHidden = false
        clarityView.isHidden = true
        if isPortrait {
            
        }else{
            landscapeFunctionView.isHidden = false
            circleConsoleView.isHidden = false
        }

    }
    
//    //切换清晰度
//    private func changeClarity(value: Int){//切换清晰度
//        //value 参数说明：1高清，2普清，4极速，100超高清
//        var resValue = 2
//        switch value {
//        case 0:
//            resValue = 4
//            downView.clarityBtn.setTitle("流畅", for: .normal)
//        case 1:
//            resValue = 2
//            downView.clarityBtn.setTitle("标清", for: .normal)
//        case 2:
//            resValue = 1
//            downView.clarityBtn.setTitle("高清", for: .normal)
//        case 3:
//            resValue = 100
//            downView.clarityBtn.setTitle("超清", for: .normal)
//        default:
//            break
//        }
//        let cgi = String(format: "GET /camera_control.cgi?param=16&value=%d&",resValue)
//        VSNet.shareinstance().sendCgiCommand(cgi, withIdentity: self.myUID)
//    }
    
    //切换清晰度
    private func changeClarity(value: Int){//切换清晰度
        DispatchQueue.global().async {[weak self] in
            guard let self = self else { return }
            VSNet.shareinstance().stopLivestream(self.myUID)
        }
        //value 参数说明：1高清，2普清，4极速，100超高清
        var resValue = 2
        switch value {
        case 0:
            resValue = 6
            DispatchQueue.main.async {[weak self] in
                guard let self = self else { return }
                self.downView.clarityBtn.setTitle("流畅", for: .normal)
            }
            
        case 1:
            resValue = 10
            DispatchQueue.main.async {[weak self] in
                guard let self = self else { return }
                self.downView.clarityBtn.setTitle("标清", for: .normal)
            }
        case 2:
            resValue = 20
            DispatchQueue.main.async {[weak self] in
                guard let self = self else { return }
                self.downView.clarityBtn.setTitle("高清", for: .normal)
            }
        case 3:
            resValue = 100
            DispatchQueue.main.async {[weak self] in
                guard let self = self else { return }
                self.downView.clarityBtn.setTitle("超清", for: .normal)
            }
        default:
            break
        }
        /*
         *  开始预览视频
         *  @param deviceIdentity 设备id
         *  @param stream         主码流 APP定为10
         *  @param substream      子码流 100 -> 2304*1296
                                        0、1、14、15、16、17、18、19、20、21、22 -> 1280*720
                                        2、3、7、8、9、10、11、12 -> 640*360
                                        5、6 -> 320*180
         */
        //开启预览视频
        DispatchQueue.global().async {[weak self] in
                guard let self = self else { return }
            VSNet.shareinstance()?.startLivestream(self.myUID, withStream: 10, withSubStream: Int32(resValue));
        }

    }
    
    private func connectVideo(){
        
        //判断当前网络是否允许
        
        if NetworkReachabilityManager.default?.status == .reachable(.cellular) {//当前为流量
            self.showToast(string: "您正在使用移动网络查看摄像画面，请注意网络消耗。")
        }
        
        let camera = CameraCache.getCamera(uid: myUID)
        let isVuid = VSNet.shareinstance()?.isVUID(myUID) ?? false
        let p2pString = getPPPPString(strDID: myUID)
        if isVuid {
            VSNet.shareinstance()?.startVUID(camera.tmpdid, withPassWord: mypwd, initializeStr: p2pString, lanSearch: 1, id: nil, add: false, vuid: myUID, lastonlineTimestamp: UInt(camera.lastTime ?? 0), withDelegate: self)
            //设置状态代理
            VSNet.shareinstance()?.setStatusDelegate(myUID, withDelegate:self)
            //设置截图，录频等功能代理
            VSNet.shareinstance().setControlDelegate(myUID, withDelegate: self)
        }else{
                let nRet = VSNet.shareinstance()?.start(myUID, withUser:"admin", withPassWord:self.mypwd, initializeStr: nil, lanSearch: 1)
                if nRet == false {
                   DispatchQueue.main.async {[weak self] in
                       VSNet.shareinstance()?.start(self?.myUID, withUser:"admin", withPassWord:self?.mypwd, initializeStr: nil, lanSearch: 1)
                       //设置连接状态回调代理
                       VSNet.shareinstance()?.setStatusDelegate(self?.myUID, withDelegate: self)
                   }
               }else{
                   
               }
        }
    }

    private func startVideo(){
        /*
         *  开始预览视频
         *  @param deviceIdentity 设备id
         *  @param stream         主码流 APP定为10
         *  @param substream      子码流 100 -> 2304*1296
                                        0、1、14、15、16、17、18、19、20、21、22 -> 1280*720
                                        2、3、7、8、9、10、11、12 -> 640*360
                                        5、6 -> 320*180
         */
        //开启预览视频
        VSNet.shareinstance()?.startLivestream(myUID, withStream: 10, withSubStream: 5);
        //设置视频数据回调代理
        VSNet.shareinstance()?.setDataDelegate(myUID, withDelegate: self);
        currentClarity = Clarity().smooth
        downView.clarityBtn.setTitle("流畅", for: .normal)
        openTime()
    }
    
    //移动方向
    //directionNum: 方向：（上左下右，0123）
    //status： 是否停止 0停止，1开启
    private func moveFrom(directionNum: Int, status: Int) {
        let onestep = 0
        var cgi = ""
        switch directionNum {
            case 0:
            if status == 0 {
                cgi = String(format: "GET /decoder_control.cgi?command=%d&onestep=%d&", CMD_PTZ_UP_STOP,onestep)
            }else{
                cgi = String(format: "GET /decoder_control.cgi?command=%d&onestep=%d&", CMD_PTZ_UP,onestep)
            }
            case 1:
            if status == 0 {
                cgi = String(format: "GET /decoder_control.cgi?command=%d&onestep=%d&", CMD_PTZ_DOWN_STOP,onestep)

            }else{
                cgi = String(format: "GET /decoder_control.cgi?command=%d&onestep=%d&", CMD_PTZ_DOWN,onestep)
            }

            case 2:
            if status == 0 {
                cgi = String(format: "GET /decoder_control.cgi?command=%d&onestep=%d&", CMD_PTZ_LEFT_STOP,onestep)

            }else{
                cgi = String(format: "GET /decoder_control.cgi?command=%d&onestep=%d&", CMD_PTZ_LEFT,onestep)
            }

            case 3:
            if status == 0 {
                cgi = String(format: "GET /decoder_control.cgi?command=%d&onestep=%d&", CMD_PTZ_RIGHT_STOP,onestep)
            }else{
                cgi = String(format: "GET /decoder_control.cgi?command=%d&onestep=%d&", CMD_PTZ_RIGHT,onestep)
            }
            default:
                break
        }
        
        VSNet.shareinstance().sendCgiCommand(cgi, withIdentity: self.myUID)

    }
    
    @objc
    private func tapAction(){
        isShowControlView = !isShowControlView
        if isShowControlView {
            showControlView()
            if isShowClarityView {
                self.hideClarityView()
            }
            //发送点击时间
            publisher.send(())
        }else{
            self.hiddenControlView()
        }
    }
    
    
    @objc
    private func handlePan(pan:UIPanGestureRecognizer) {
        if isLockScreen {return}
        let translation = pan.translation(in: displayView?.superview)
        let direct = determineCameraDirection(translation: translation)
        if direction != direct {
            switch direction {
            case .CircleConsoleMoveDirectionUp:
                ZTLog("结束向上移动")
                self.moveFrom(directionNum: 0, status: 0)
            case .CircleConsoleMoveDirectionDown:
                ZTLog("结束向下移动")
                self.moveFrom(directionNum: 1, status: 0)

            case .CircleConsoleMoveDirectionLeft:
                ZTLog("结束向左移动")
                self.moveFrom(directionNum: 2, status: 0)

            case .CircleConsoleMoveDirectionRight:
                ZTLog("结束向右移动")
                self.moveFrom(directionNum: 3, status: 0)
            default:
                break
            }
            
            switch direct {
            case .CircleConsoleMoveDirectionUp:
                ZTLog("开始向上移动")
                self.moveFrom(directionNum: 0, status: 1)
            case .CircleConsoleMoveDirectionDown:
                ZTLog("开始向下移动")
                self.moveFrom(directionNum: 1, status: 1)
            case .CircleConsoleMoveDirectionLeft:
                ZTLog("开始向左移动")
                self.moveFrom(directionNum: 2, status: 1)
            case .CircleConsoleMoveDirectionRight:
                ZTLog("开始向右移动")
                self.moveFrom(directionNum: 3, status: 1)
            default:
                break
            }
            direction = direct
        }

        if pan.state == .ended {//结束后移动方向回到原位
            switch direction {
            case .CircleConsoleMoveDirectionUp:
                ZTLog("结束向上移动")
                self.moveFrom(directionNum: 0, status: 0)
            case .CircleConsoleMoveDirectionDown:
                ZTLog("结束向下移动")
                self.moveFrom(directionNum: 1, status: 0)

            case .CircleConsoleMoveDirectionLeft:
                ZTLog("结束向左移动")
                self.moveFrom(directionNum: 2, status: 0)

            case .CircleConsoleMoveDirectionRight:
                ZTLog("结束向右移动")
                self.moveFrom(directionNum: 3, status: 0)
            default:
                break
            }
            direction = .CircleConsoleMoveDirectionNone
        }
        
    }
    
    private func determineCameraDirection(translation: CGPoint ) -> CircleConsoleMoveDirection{
        var direc = CircleConsoleMoveDirection.CircleConsoleMoveDirectionNone
        if translation.y == 0 || abs(translation.x / translation.y) >= 1.0 {
            if translation.x > 0.0 {
                //向右
                direc = .CircleConsoleMoveDirectionRight
            }else{
                //想左
                direc = .CircleConsoleMoveDirectionLeft
            }
        }else if translation.x == 0.0 || abs(translation.y / translation.x) >= 1.0 {
            if translation.y > 0.0 {
                direc = .CircleConsoleMoveDirectionDown
            }else{
                direc = .CircleConsoleMoveDirectionUp
            }
        }else{
            direc = .CircleConsoleMoveDirectionNone
        }
        
        return direc
    }
    
    //展示控件
    private func showControlView(){
        downView.alpha = 1
        downView.isHidden = false
        self.circleConsoleView.alpha = 1
        self.circleConsoleView.isHidden = false

        if !isPortrait{
            self.landscapeFunctionView.alpha = 1
            self.landscapeFunctionView.isHidden = false
            self.headerView.alpha = 1
            self.headerView.isHidden = false
        }
    }
        
    //隐藏控件
    private func hiddenControlView(){
            UIView.animate(withDuration: 0.3) {[weak self] in
                //隐藏控件
                self?.downView.alpha = 0
                if !self!.isPortrait{
                    self?.circleConsoleView.alpha = 0
                    self?.landscapeFunctionView.alpha = 0
                    self?.headerView.alpha = 0
                }
            } completion: {[weak self] finish in
                if finish {
                    self?.downView.isHidden = true
                    self?.isShowControlView = false
                    if !self!.isPortrait{
                        self?.circleConsoleView.isHidden = true
                        self?.landscapeFunctionView.isHidden = true
                        self?.headerView.isHidden = true
                    }
                }
            }
    }

    private func getPPPPString(strDID: String) -> String? {
        if strDID.uppercased().contains("VSTG") {
            return "EEGDFHBOKCIGGFJPECHIFNEBGJNLHOMIHEFJBADPAGJELNKJDKANCBPJGHLAIALAADMDKPDGOENEBECCIK:vstarcam2018"
        } else if strDID.uppercased().contains("VSTH") {
            return "EEGDFHBLKGJIGEJLEKGOFMEDHAMHHJNAGGFABMCOBGJOLHLJDFAFCPPHGILKIKLMANNHKEDKOINIBNCPJOMK:vstarcam2018"
        } else if strDID.uppercased().contains("VSTJ") {
            return "EEGDFHBLKGJIGEJNEOHEFBEIGANCHHMBHIFEAHDEAMJCKCKJDJAFDDPPHLKJIHLMBENHKDCHPHNJBODA:vstarcam2019"
        } else if strDID.uppercased().contains("VSTK") {
            return "EBGDEJBJKGJFGJJBEFHPFCEKHGNMHNNMHMFFBICPAJJNLDLLDHACCNONGLLPJGLKANMJLDDHODMEBOCIJEMA:vstarcam2019"
        } else if strDID.uppercased().contains("VSTM") {
            return "EBGEEOBOKHJNHGJGEAGAEPEPHDMGHINBGIECBBCBBJIKLKLCCDBBCFODHLKLJJKPBOMELECKPNMNAICEJCNNJH:vstarcam2019"
        } else if strDID.uppercased().contains("VSTN") {
            return "EEGDFHBBKBIFGAIAFGHDFLFJGJNIGEMOHFFPAMDMAAIIKBKNCDBDDMOGHLKCJCKFBFMPLMCBPEMG:vstarcam2019"
        } else if strDID.uppercased().contains("VSTL") {
            return "EEGDFHBLKGJIGEJIEIGNFPEEHGNMHPNBGOFIBECEBLJDLMLGDKAPCNPFGOLLJFLJAOMKLBDFOGMAAFCJJPNFJP:vstarcam2019"
        } else if strDID.uppercased().contains("VSTP") {
            return "EEGDFHBLKGJIGEJLEIGJFLENHLNBHCNMGAFGBNCOAIJMLKKODNALCCPKGBLHJLLHAHMBKNDFOGNGBDCIJFMB:vstarcam2019"
        } else if strDID.uppercased().contains("VSTF") {
            return "HZLXEJIALKHYATPCHULNSVLMEELSHWIHPFIBAOHXIDICSQEHENEKPAARSTELERPDLNEPLKEILPHUHXHZEJEEEHEGEM-$$"
        } else if strDID.uppercased().contains("VSTD") {
            return "HZLXSXIALKHYEIEJHUASLMHWEESUEKAUIHPHSWAOSTEMENSQPDLRLNPAPEPGEPERIBLQLKHXELEHHULOEGIAEEHYEIEK-$$"
        } else if strDID.uppercased().contains("VSTA") {
            return "EFGFFBBOKAIEGHJAEDHJFEEOHMNGDCNJCDFKAKHLEBJHKEKMCAFCDLLLHAOCJPPMBHMNOMCJKGJEBGGHJHIOMFBDNPKNFEGCEGCBGCALMFOHBCGMFK"
        } else if strDID.uppercased().contains("VSTB") {
            return "ADCBBFAOPPJAHGJGBBGLFLAGDBJJHNJGGMBFBKHIBBNKOKLDHOBHCBOEHOKJJJKJBPMFLGCPPJMJAPDOIPNL"
        } else if strDID.uppercased().contains("VSTC") {
            return "ADCBBFAOPPJAHGJGBBGLFLAGDBJJHNJGGMBFBKHIBBNKOKLDHOBHCBOEHOKJJJKJBPMFLGCPPJMJAPDOIPNL"
        } else {
            return nil
        }
    }
    
    //开启监听
    @objc private func audioAction(){
        //如果已开启对讲，则无法监听
        if isOpenTalk {
            return
        }
        isOpenVoice = !isOpenVoice
        landscapeFunctionView.cameraControlDatas[3].isSelected = isOpenVoice
        cameraFunciondatas[3].isSelected = isOpenVoice
        landscapeFunctionView.collectionView.reloadData()
        functionCollectionView.reloadData()
        if isOpenVoice {
            VSNet.shareinstance().startAudio(self.myUID, withEchoCancellationVer: false)
        }else{
            VSNet.shareinstance().stopAudio(self.myUID)
        }
    }
    //开启对讲
    @objc private func talkAction(){
        isOpenTalk = !isOpenTalk
        landscapeFunctionView.cameraControlDatas[2].isSelected = isOpenTalk
        cameraFunciondatas[2].isSelected = isOpenTalk
        landscapeFunctionView.collectionView.reloadData()
        functionCollectionView.reloadData()
        if isOpenTalk {
            //对讲（摄像机扬声器）开启后，自动关闭声音（摄像机麦克风声）
            if isOpenVoice {//关闭监听
                landscapeFunctionView.cameraControlDatas[3].isSelected = false
                cameraFunciondatas[3].isSelected = false
                landscapeFunctionView.collectionView.reloadData()
                functionCollectionView.reloadData()
                VSNet.shareinstance().stopAudio(self.myUID)
            }
            VSNet.shareinstance().startTalk(self.myUID, withEchoCancellationVer: false)
        }else{
            VSNet.shareinstance().stopTalk(self.myUID)
        }
    }

    //上下巡航
    @objc private func updownAction(){
        isOpenUpdown = !isOpenUpdown
        controllerView.cameraControlDatas[1].isSelected = isOpenUpdown
        controllerView.controlCollectionView.reloadData()
        downView.upDownBtn.isSelected = isOpenUpdown

        if isOpenUpdown {
            let onestep = 0
            let cgi = String(format: "GET /decoder_control.cgi?command=%d&onestep=%d&", CMD_PTZ_UP_DOWN,onestep)
            VSNet.shareinstance().sendCgiCommand(cgi, withIdentity: myUID)
        }else{
            let onestep = 0
            let cgi = String(format: "GET /decoder_control.cgi?command=%d&onestep=%d&", CMD_PTZ_UP_DOWN_STOP,onestep)
            VSNet.shareinstance().sendCgiCommand(cgi, withIdentity: myUID)
            self.showToast(string: "上下巡航结束")
        }
    }
    
    private func lockTheFrames() {
        isLockScreen = !isLockScreen
        if isLockScreen {
            self.showToast(string: "摄像画面已锁定")
        }
        controllerView.cameraControlDatas[3].isSelected = isLockScreen
        controllerView.controlCollectionView.reloadData()
        lockBtn.isSelected = isLockScreen
    }

    
    //开启时间
    private func openTime(){
        let cgi = String(format: "camera_control.cgi?param=10&value=%d&", 1)
        VSNet.shareinstance().sendCgiCommand(cgi, withIdentity: myUID)
    }
    
    //左右巡航
    @objc private func leftRightAction(){
        isOpenLeftRight = !isOpenLeftRight
        controllerView.cameraControlDatas[0].isSelected = isOpenLeftRight
        controllerView.controlCollectionView.reloadData()
        downView.leftRightBtn.isSelected = isOpenLeftRight
        if isOpenLeftRight {
            let onestep = 0
            let cgi = String(format: "GET /decoder_control.cgi?command=%d&onestep=%d&", CMD_PTZ_LEFT_RIGHT,onestep)
            VSNet.shareinstance().sendCgiCommand(cgi, withIdentity: myUID)
        }else{
            let onestep = 0
            let cgi = String(format: "GET /decoder_control.cgi?command=%d&onestep=%d&", CMD_PTZ_LEFT_RIGHT_STOP,onestep)
            VSNet.shareinstance().sendCgiCommand(cgi, withIdentity: myUID)
            self.showToast(string: "左右巡航结束")
        }
    }

    //屏幕截图
    @objc private func screenshotAction(){
        isNeedSnapshot = true
        VSNet.shareinstance().sendCgiCommand("snapshot.cgi?res=1&", withIdentity: myUID)
    }
    
    //收藏位置
    private func collectionPlace(){
        let places = CommonPlaceCache.getCameraCommonPlaces(uid: myUID)
        if places.count >= 6 {
            self.showToast(string: "最多可保存6个常看位置")
            return
        }else{

            var commonPlace = 0
            if !places.map(\.commonPlace).contains(Int(CMD_PTZ_PREFAB_BIT_SET0)) {//预设一
                commonPlace = Int(CMD_PTZ_PREFAB_BIT_SET0)
            }else if !places.map(\.commonPlace).contains(Int(CMD_PTZ_PREFAB_BIT_SET1)) {//预设二
                commonPlace = Int(CMD_PTZ_PREFAB_BIT_SET1)
            }else if !places.map(\.commonPlace).contains(Int(CMD_PTZ_PREFAB_BIT_SET2)) {//预设三
                commonPlace = Int(CMD_PTZ_PREFAB_BIT_SET2)
            }else if !places.map(\.commonPlace).contains(Int(CMD_PTZ_PREFAB_BIT_SET3)) {//预设四
                commonPlace = Int(CMD_PTZ_PREFAB_BIT_SET3)
            }else if !places.map(\.commonPlace).contains(Int(CMD_PTZ_PREFAB_BIT_SET4)) {//预设五
                commonPlace = Int(CMD_PTZ_PREFAB_BIT_SET4)
            }else if !places.map(\.commonPlace).contains(Int(CMD_PTZ_PREFAB_BIT_SET5)) {//预设六
                commonPlace = Int(CMD_PTZ_PREFAB_BIT_SET5)
            }
            
            currentCommonPlace = commonPlace
            isCollectingPlace = true
            //发送收藏位置指令
            let cgi = String(format: "GET /decoder_control.cgi?command=%d&onestep=0&", currentCommonPlace)
            VSNet.shareinstance().sendCgiCommand(cgi, withIdentity: myUID)
            
        }
    }
    
    
    private func showCollectionAlert(image: Data){
        let alert = CameraCollectingAlert()
        let img = UIImage(data: image)
        alert.placeImgView.image = img
        self.view.addSubview(alert)
        self.view.bringSubviewToFront(alert)
        alert.clickCallback = {[weak self] name in
            ZTLog("收藏位置保存成功")
            DispatchQueue.main.async {[weak self] in
                self?.showToast(string: "保存成功")
            }
            CommonPlaceCache.cacheCommonPlace(uid: self?.myUID, commonPlace: self?.currentCommonPlace ?? 0, placeName: name, commonPlaceData: image )
        }
    }
    
    
    //查看收藏的位置
    private func showCommonPlaceAlert(){
        let places = CommonPlaceCache.getCameraCommonPlaces(uid: myUID)
        
        let alert = CameraPlacesAlert()
        alert.items = places
        alert.emptyView.isHidden = places.count != 0
        //点击回调
        alert.clickCallback = {[weak self] index in
            self?.setPlace(place: places[index])
        }
        //删除回调
        alert.deletedCallback = {[weak self] places in
            CommonPlaceCache.deleteCameraCommonPlaces(places: places, uid: self?.myUID ?? "nil")
            self?.showToast(string: "删除成功")
        }
        self.view.addSubview(alert)
        self.view.bringSubviewToFront(alert)
        
    }
    
    //调用收藏的位置
    private func setPlace(place: CameraCommonPlaceModel){
        var cgi = ""
        switch place.commonPlace {
        case Int(CMD_PTZ_PREFAB_BIT_SET0):
            //位置一
             cgi = String(format: "GET /decoder_control.cgi?command=%d&onestep=0&", CMD_PTZ_PREFAB_BIT_RUN0)
        case Int(CMD_PTZ_PREFAB_BIT_SET1):
            //位置二
             cgi = String(format: "GET /decoder_control.cgi?command=%d&onestep=0&", CMD_PTZ_PREFAB_BIT_RUN1)
        case Int(CMD_PTZ_PREFAB_BIT_SET2):
            //位置三
             cgi = String(format: "GET /decoder_control.cgi?command=%d&onestep=0&", CMD_PTZ_PREFAB_BIT_RUN2)
        case Int(CMD_PTZ_PREFAB_BIT_SET3):
            //位置四
             cgi = String(format: "GET /decoder_control.cgi?command=%d&onestep=0&", CMD_PTZ_PREFAB_BIT_RUN3)
        case Int(CMD_PTZ_PREFAB_BIT_SET4):
            //位置五
             cgi = String(format: "GET /decoder_control.cgi?command=%d&onestep=0&", CMD_PTZ_PREFAB_BIT_RUN4)
        case Int(CMD_PTZ_PREFAB_BIT_SET5):
            //位置六
             cgi = String(format: "GET /decoder_control.cgi?command=%d&onestep=0&", CMD_PTZ_PREFAB_BIT_RUN5)
        default:
            break
        }
        VSNet.shareinstance().sendCgiCommand(cgi, withIdentity: myUID)
        self.showToast(string: "摄像机正在转向“\(place.placeName)”,请稍等...")
    }
    
    //屏幕录频
    @objc private func recordVideoAction(){
        isRecord = !isRecord
        landscapeFunctionView.cameraControlDatas[1].isSelected = isRecord
        cameraFunciondatas[1].isSelected = isRecord
        landscapeFunctionView.collectionView.reloadData()
        functionCollectionView.reloadData()
        if isRecord {//开始录频
            let dateFormatter = DateFormatter()
            dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
            let currentTime = dateFormatter.string(from: Date())
            let filepath = ZTZipTool.getDocumentPath() + "/" + myUID

            if ZTZipTool.fileExists(path: filepath) {
                //删除原有文件夹
                ZTZipTool.deleteFromPath(path: filepath)
            }
            //创建新的文件夹
            ZTZipTool.createFolder(fileName: myUID, path: ZTZipTool.getDocumentPath())
            //用时间记录录制的视频片段
            let fileName = filepath + "/" + currentTime + ".mp4"
            ZTLog(fileName)
            
            //开始录制
            recordBGView.isHidden = false
            view.bringSubviewToFront(recordBGView)
            //开启计时器
            timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(videoRecordingTotolTime), userInfo: nil, repeats: true)

            VSNet.shareinstance().startRecord(fileName, cameraUid: myUID) { success, error in
                if success {
                    ZTLog("录制成功")
                    DispatchQueue.global().async { [weak self] in
                        guard let self = self else { return }
                        if UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(fileName) {
                            UISaveVideoAtPathToSavedPhotosAlbum(fileName, self, #selector(self.videoDidFinishSaving(videoPath:error:contextInfo:)), nil)
                        }
                    }
                    
                }else{
                    ZTLog("录制失败:\(error)")
                }
            }
            
        }else{//停止录频
            DispatchQueue.global().async { [weak self] in
                VSNet.shareinstance().stopCameraUid(self?.myUID)
                DispatchQueue.main.async { [weak self] in
                    self?.secondCount = 0
                    self?.timer?.invalidate()
                    self?.recordBGView.isHidden = true
                }
            }
        }
    }
    
    //录制时间
    @objc
    private func videoRecordingTotolTime(){
        secondCount += 1
        
        if secondCount == 600 {
            timer?.invalidate()
        }
        
//        let hours = secondCount / 3600
        let mintues = (secondCount % 3600) / 60
        let seconds = secondCount % 60
        
        timeLabel.text = String(format: "%02d:%02d",mintues,seconds)
    }

    //视频保存进系统相册回调
    @objc private func videoDidFinishSaving(videoPath:String, error: Error?, contextInfo: Any) {

        DispatchQueue.main.async {[weak self] in
            self?.showToast(string: "录像已保存至手机相册")
        }

    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        //隐藏操作栏
        cameraFunciondatas[4].isSelected = false
        controllerView.isHidden = !cameraFunciondatas[4].isSelected
        functionCollectionView.reloadData()
    }
}


extension CameraViewController: VSNetStatueProtocol, VSNetDataProtocol {
    //VSNetStatueProtocol 设备状态回调代理
    func vsNetStatus(_ deviceIdentity: String!, statusType: Int, status: Int) {
        if(deviceIdentity != myUID){
            return
        }
    }
    
    
    func vsNetStatus(fromVUID strVUID: String!, uid strUID: String!, statusType: Int, status: Int) {
        ZTLog("statusType: \(statusType) status: \(status)")
        if statusType == VSNET_NOTIFY_TYPE_VUIDSTATUS.rawValue {
            //更新摄像机信息
            let camera = CameraCache.getCamera(uid: strVUID)
            camera.uid = strVUID
            camera.tmpdid = strUID
            CameraCache.update(from: camera)

            switch status {
            case Int(VUIDSTATUS_CONNECTING.rawValue):
                    //正在连接中
                    DispatchQueue.main.async {
                    self.showToast(string: "摄像头正在连接中")
                    self.placehoderLabel.text = "摄像头正在连接中..."
                    }
            case Int(VUIDSTATUS_CONNECT_TIMEOUT.rawValue):
                    //连接超时
                    DispatchQueue.main.async {
                    self.showToast(string: "摄像头连接超时")
                    self.placehoderLabel.text = "摄像头连接超时..."
                    //三秒后重连
                    DispatchQueue.main.asyncAfter(deadline: .now() + 3) { [weak self] in
                        guard let self = self else {return}
                        self.connectVideo()
                    }
                    }
                    VSNet.shareinstance().stop(self.myUID)
            case Int(VUIDSTATUS_DEVICE_NOT_ON_LINE.rawValue):
                    //设备离线
                    DispatchQueue.main.async {
                    self.showToast(string: "摄像头已离线")
                    self.placehoderLabel.text = "摄像头已离线..."
                    }
                    VSNet.shareinstance().stop(self.myUID)
            case Int(VUIDSTATUS_CONNECT_FAILED.rawValue):
                    //设备连接失败
                    DispatchQueue.main.async {
                    self.showToast(string: "摄像头连接失败")
                    self.placehoderLabel.text = "摄像头连接失败..."
                    //三秒后重连
                    DispatchQueue.main.asyncAfter(deadline: .now() + 3) { [weak self] in
                        guard let self = self else {return}
                        self.connectVideo()
                    }
                    }
                    VSNet.shareinstance().stop(self.myUID)
            case Int(VUIDSTATUS_INVALID_USER_PWD.rawValue):
                    //用户名或密码错误
                    DispatchQueue.main.async {
                    self.showToast(string: "用户名或密码错误")
                    self.placehoderLabel.text = "用户名或密码错误"
                    }
                    VSNet.shareinstance().stop(self.myUID)
            case Int(VUIDSTATUS_ON_LINE.rawValue):
                    //设备在线
                    //连接成功，在线
                    DispatchQueue.main.async {
                        self.showToast(string: "摄像头连接成功")
                        self.placehoderLabel.text = "摄像头连接成功..."
                        self.startVideo()
                        self.isShowControlView = false
                        self.tapAction()
                    }

            default:
                    break
            }
            
            
            if(VUIDSTATUS_VUID_VERIFICATION_FAIL.rawValue == status || VUIDSTATUS_VUID_VERIFICATION_UIDCHANGE.rawValue == status)
            {
                //延时3秒再去连接
                DispatchQueue.main.asyncAfter(deadline: .now() + 3) { [weak self] in
                    VSNet.shareinstance()?.startVUID(nil, withPassWord:self?.mypwd, initializeStr: nil, lanSearch: 1, id: nil, add: false, vuid: strVUID, lastonlineTimestamp: 0, withDelegate: self)

                }
            }
            
            return
        } else if statusType == VSNET_NOTIFY_TYPE_VUIDTIME.rawValue {
            //更新已连接的VUID时间
            CameraCache.updateVUIDLastConnetTime(did: myUID, tmpDid: strUID, time: status)
        }

    }
        
    
    //VSNetDataProtocol 视频数据回调代理
    func vsNetYuvData(_ deviceIdentity: String!, data buff: UnsafeMutablePointer<UInt8>!, withLen len: Int, height: Int, width: Int, time timestame: UInt, origenelLen oLen: Int) {
        if(deviceIdentity != myUID){
            return
        }
        
        DispatchQueue.main.async {[weak self] in
            self?.setupGLView()
        }
        //buff 是解码出来的视频数据。要及时使用或者保存起来，出了作用域(跳出回调方法)后就会释放掉。
        DispatchQueue.main.sync {[weak self] in
            var overlay : SDL_VoutOverlay = SDL_VoutOverlay(w: Int32(Int(width)), h: Int32(Int(height)), pitches: (UInt16(width),UInt16(width) / 2,UInt16(width) / 2), pixels: (buff, buff + width * height, buff + width * height * 5 / 4))
//            self.displayView.frame = CGRect(x: 0, y: 0, width: Screen.screenWidth, height: Screen.screenHeight/Screen.screenWidth * CGFloat(width))
            self?.displayView?.display(&overlay)
        }
    }
    
    func vsNetVideoData(_ deviceIdentity: String!, length: Int32) {
        
    }
    
    func vsNetH264Data(_ deviceIdentity: String!, data buff: UnsafeMutablePointer<UInt8>!, withLen len: Int, height: Int, width: Int, time timestame: UInt, withType type: Int) {
        
    }
    

    func vsNetHardH264Data(_ deviceIdentity: String!, data pixeBuffer: CVPixelBuffer!, time timestame: UInt, origenelLen oLen: Int) {
        
    }
    
    func vsNetImageNotify(_ deviceIdentity: String!, withImage imageData: Data!, timestamp: Int) {
        
    }
    
    func vsNetParamNotify(_ paramType: Int32, params: UnsafeMutableRawPointer!) {
        
    }
    
    func vsNetVideoBufState(_ deviceIdentity: String!, state: Int32) {
        
    }
}

extension CameraViewController: VSNetControlProtocol {
    
    func vsNetControl(_ deviceIdentity: String!, commandType comType: Int, buffer retString: String!, length: Int32, charBuffer buffer: UnsafeMutablePointer<CChar>!) {
        
        ZTLog("VSNet返回数据 UID:\(String(describing: deviceIdentity)), comtype \(comType)")
        switch comType {
        case Int(CGI_IESET_SNAPSHOT):
            let imageData = Data(bytes: buffer, count: Int(length))
            let image = UIImage(data: imageData)
            if isNeedSnapshot {//是手动截图的才需要保存进相册
                //如果是通过预设位置截图的不需要保存
                if isCollectingPlace {
                    DispatchQueue.main.async {[weak self] in
                        self?.showCollectionAlert(image: imageData)
                        self?.isCollectingPlace = false
                        self?.isNeedSnapshot = false
                    }
                    
                    return
                }
                DispatchQueue.main.async {[weak self] in
                    UIImageWriteToSavedPhotosAlbum(image ?? UIImage(), nil, nil, nil)
                    self?.showToast(string: "截图已保存至手机相册")
                    self?.isNeedSnapshot = false

                }
            }

        case Int(CGI_DECODER_CONTROL):
            guard let result = retString else {
                return
            }
            
            if isCollectingPlace {
                if result.contains("ok") {
                    self.screenshotAction()
                }
            }
        case Int(CGI_IESET_USER):
            ZTLog(retString)
        default:
            break
        }
    }

}

extension CameraViewController: UICollectionViewDelegate, UICollectionViewDataSource {
    //cell 数量
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return cameraFunciondatas.count
    }
    //cell 具体内容
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CameraFunctionCell.reusableIdentifier, for: indexPath) as! CameraFunctionCell
        if cameraFunciondatas[indexPath.item].isSelected {
            cell.iconView.image = cameraFunciondatas[indexPath.item].selectedIcon
        }else{
            cell.iconView.image = cameraFunciondatas[indexPath.item].normalIcon
        }

        return cell
    }

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        //刷新
        collectionView.reloadData()
        switch indexPath.item {
        case 0://截图
            screenshotAction()
        case 1://录制
            recordVideoAction()
        case 2://对讲
            talkAction()
        case 3://监听
            audioAction()
        case 4://全部
            cameraFunciondatas[indexPath.item].isSelected = !cameraFunciondatas[indexPath.item].isSelected
            controllerView.isHidden = !cameraFunciondatas[indexPath.item].isSelected
            if !controllerView.isHidden {
                self.view.bringSubviewToFront(controllerView)
            }
        default:
            break
        }
    }
    
}

class CameraFuctionModel : BaseModel {
    var normalIcon: UIImage?
    var selectedIcon: UIImage?
    var isSelected = false
    var title = ""
}

#endif
